﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNet.Common.Kit;

namespace taobaoSpider
{
    //店铺首页模型
    public class HtmlShopIndex
    {
        private ShowErrorLogEventHandler ShowErrHandler = null;
        LogerHelper logger = new LogerHelper(DirType.Local, MessageType.Exception);
        static int ipIndex = 0, ipCount = 1;string currentIP="本机IP"; //代理服务器时用来计算取的索引和代理IP总数目

        string _shopUrl = "";  //input value;
        string _shopId="";//output 
        string _xyRank="";  //信用等级 output
        string _createDate=""; //创建日期。output
        string _userId = ""; //用户ID  output
        string _sjName = "";//设计师   output
        string _shopTitle = ""; //标题 output
        string _dpVer = "";   //店铺版本  output
        string _templateID = ""; //模板ID output
        string _nickName = "";  //掌柜名  output

        IniHelper ini = new DotNet.Common.Kit.IniHelper("HtmlNodeXPath.ini");
        HttpHelper httpHelper = new HttpHelper();
        HttpItem item = new HttpItem();
        ShowErrorLogEventArgs e = new ShowErrorLogEventArgs();
        System.Windows.Forms.Label lblInfo = new System.Windows.Forms.Label();
        //lblInfo.Name = "lblInfo";
        System.Windows.Forms.Label lblIpInfo = new System.Windows.Forms.Label();
        //lblIpInfo.Name = "lblIpInfo";


        public string DPVer
        {
            get { return _dpVer; }
        }
        public string TemplateID
        {
            get { return _templateID; }
        }
        public string NickName
        {
            get { return _nickName; }
        }
        public string ShopTitle
        {
            get { return _shopTitle; }
        }
        public string SJName
        {
            get { return _sjName; }
        }


        public string ShopURL
        {
            set { _shopUrl = value; }
            get { return _shopUrl; }
        }

        public string ShopID
        {
            get { return _shopId; }
        }

        public string XyRank {
            get { return _xyRank; }
        }
        public string CreateDate
        {
            get { return _createDate; }
        }

        public string UserID
        {
            get { return _userId; }
        }

        /// <summary>
        /// 多线程版本的构造函数。
        /// </summary>
        /// <param name="showErr"></param>
        /// <param name="shopUrl"></param>
        public HtmlShopIndex(ShowErrorLogEventHandler showErr)
        {
            this.ShowErrHandler = showErr;
            //this._shopUrl = shopUrl;
            lblInfo.Name = "lblInfo";
            lblIpInfo.Name = "lblIpInfo";
        }

        /// <summary>
        /// 非线程版本。
        /// </summary>
        /// <param name="shopUrl"></param>
        public HtmlShopIndex(string shopUrl)
        {
            this._shopUrl = shopUrl;
            lblInfo.Name = "lblInfo";
            lblIpInfo.Name = "lblIpInfo";
        }

        /// <summary>
        /// 解析While循环中的htmlStr得到相应的值。
        /// </summary>
        /// <param name="htmlStr"></param>
        /// <returns></returns>
        private string ParseHtmlStrWhile(string htmlStr)
        {
            if (htmlStr.Contains("title"))  //说明返回为一个HTML页面
            {
                HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);
                htmlStr = doc.DocumentNode.SelectNodes("//title")[0].InnerText.Trim('\r', '\n');
                return htmlStr;
            }
            else
            {
                if (htmlStr.Contains("body"))
                {
                    HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);
                    htmlStr = doc.DocumentNode.SelectNodes("//body")[0].InnerText.Trim('\r', '\n');
                    return htmlStr;
                }
                else
                {
                    return htmlStr;
                }
            }
        }
        public int InitDianpuIndex()
        {
            int ret = 0;
            item.URL = _shopUrl;
            item.Allowautoredirect = true; //自动跳转
            item.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)";
            HtmlHttp http = new HtmlHttp();
            string htmlStr = httpHelper.GetHtml(item).Html;
            HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);

            HtmlAgilityPack.HtmlNodeCollection hdHnc=doc.DocumentNode.SelectNodes("//div[@id='hd']");
            HtmlAgilityPack.HtmlNodeCollection bdHnc = doc.DocumentNode.SelectNodes("//div[@id='bd']");
            DateTime closeInitTime = DateTime.Now; //标识关机时间起点。
            while (hdHnc == null && bdHnc == null)//应该有一个退出机制，避免出现死循环
            {
                DateTime closeEndTime = DateTime.Now;
                string htmlStrTitle = ParseHtmlStrWhile(htmlStr); //用来标识进入路由重启或换IP的标识串。
                e.ErrPosition = "ShopIndex:InitDianpuIndex()=>while";
                //////start  更新数据要联动
                e.ErrMessage = htmlStrTitle;
                logger.LogToFile(e.ErrPosition + e.ErrMessage + "--" + _shopUrl);
                e.ErrMessage = htmlStrTitle + "  店铺主页:" + _shopUrl;
                this.ShowErrHandler(lblInfo, e);
                //e.ErrMessage ="本次使用IP：" + currentIP;
                //this.ShowErrHandler(lblIpInfo, e);
                ///////////end

                if (closeEndTime > closeInitTime.AddMinutes(5)) //超时10分钟则进入关机程序或者换代理IP
                {
                    if (ini.GetKeyValue("ProxyUseFlag", "closeSys") == "0")  //进入关机程序
                    {
                        e.ErrMessage = "开始循环时间：" + closeInitTime + "  结束循环关机时间" + closeEndTime;

                        logger.LogToFile(e.ErrPosition + "--超时5分钟关机--" + htmlStrTitle);
                        //e.ErrMessage = "--超时5分钟关机--" + htmlStrTitle;
                        //ShowErrHandler(lblInfo, e);
                        //e.ErrMessage = "可用代理IP数：-1" + "\r\n" + "IP索引：-1" + "\r\n" + "本次使用IP：" + currentIP;
                        //this.ShowErrHandler(lblIpInfo, e);

                        //this.ShowErrHandler("closeSys", e);//调用关机程序
                    }
                    if (ini.GetKeyValue("ProxyUseFlag", "closeSys") == "1")  //换是个机IP访问
                    {//对于不关机程序，超时5分钟则退出本次循环
                        //if (currentIP == "本机IP" || currentIP == "")
                        //{
                        //    item.ProxyIp = "";
                        //    TBWS.tb_wsSoapClient client = new TBWS.tb_wsSoapClient();
                        //    currentIP = client.GetReqIp() + "(本机IP)";
                        //}
                        //htmlStr = httpHelper.GetHtml(item).Html;
                        //htmlStrTitle = ParseHtmlStrWhile(htmlStr); //用来标识进入路由重启或换IP的标识串。
                        //以下三者信息进行联动，便于监测程序运行状况
                        logger.LogToFile(e.ErrPosition + "--超时5分钟退出本次while--" + htmlStrTitle+"  URL:"+this._shopUrl+" Nickname:"+this._nickName);
                        //e.ErrMessage = "--超时5分钟换本机IP--" + htmlStrTitle;
                        //this.ShowErrHandler(lblInfo, e);
                        //e.ErrMessage = "可用代理IP数：-1" + "\r\n" + "IP索引：-1" + "\r\n" + "本次使用IP：" + currentIP;
                        //this.ShowErrHandler(lblIpInfo, e);
                        break;  //http://shop71906861.taobao.com/这样的找不到店铺信息，退出本次while
                    }
                }
                Dictionary<string, string> dict = ini.SectionValuesEx("ReConnectRouter"); //读取INI中设定的重启路由的条件
                if (GlobalFun.ExistDict(dict, htmlStrTitle))
                {
                    if (ini.GetKeyValue("ProxyUseFlag", "proxy") == "0")
                    {
                        currentIP = Router.DisConnect();
                        logger.LogToFile(e.ErrPosition + "  重启路由IP:" + currentIP);
                        e.ErrMessage = htmlStrTitle + "  " + this._shopUrl;
                        ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "重启路由IP:" + ipCount + "\r\n" + "IP索引--" + ipIndex + "\r\n" + "本次使用IP--" + currentIP;
                        this.ShowErrHandler(lblIpInfo, e);
                    }
                    if (ini.GetKeyValue("ProxyUseFlag", "proxy") == "1")
                    {
                        //if (ipCount != 0)
                        //    ipIndex = ipIndex % ipCount;
                        ipIndex = 0;
                        Router.ShowErrHandler = this.ShowErrHandler;
                        string vtime = "";
                        currentIP = Router.ProxyIp(ref ipIndex, ref ipCount,ref vtime);
                        if (currentIP == "本机IP"||currentIP=="")
                        {
                            item.ProxyIp = "";
                            TBWS.tb_wsSoapClient client = new TBWS.tb_wsSoapClient();
                            currentIP = client.GetReqIp() + "(本机IP)";
                        }
                        logger.LogToFile(e.ErrPosition + "代理IP数--" + ipCount + "--第" + ipIndex + "--号IP：" + currentIP);
                        e.ErrMessage = htmlStrTitle+"  "+this._shopUrl;
                        ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "可用代理IP数：" + ipCount + "\r\n" + "IP索引：" + ipIndex + "\r\n" + "本次使用IP：" + currentIP + "(速度:" + vtime + " s)";
                        this.ShowErrHandler(lblIpInfo, e);
                       // ipIndex++;
                        
                    }
                }
                DateTime d1 = DateTime.Now;
                htmlStr = httpHelper.GetHtml(item).Html;
                DateTime d2 = DateTime.Now;
                Router.RefreshTime(currentIP, (d2 - d1).Ticks / 10000);
                doc = GlobalFun.ParaseToHtml(htmlStr);

                hdHnc = doc.DocumentNode.SelectNodes("//div[@id='hd']");
                bdHnc = doc.DocumentNode.SelectNodes("//div[@id='bd']");
            }
            if (htmlStr.Contains("没有找到相应的店铺信息"))
            {
                e.ErrPosition = "ShopIndex:InitDianpuIndex()=> if (htmlStr.Contains(没有找到相应的店铺信息))";
                e.ErrMessage = "未能找到掌柜--" + this._nickName + "--首页--" + this._shopUrl + "--店铺信息";
                this.ShowErrHandler(lblInfo, e);
                logger.WriteErrorLog(e.ErrPosition+e.ErrMessage);
            }
            HtmlAgilityPack.HtmlNodeCollection hncTitle = doc.DocumentNode.SelectNodes("//title");
            if (hncTitle != null)//对其他网络异常的补充判断。保证程序不要出错，但可以会漏掉该条记录
            {
                string titleTemp = hncTitle[0].InnerText.Trim();  //用来标识店铺类型。
                //最原始店铺:标题中含有“淘宝网”但不含有“首页” <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                if (titleTemp.Contains("淘宝网") && (!titleTemp.Contains("首页")) && (htmlStr.Trim().Substring(0, 15).ToLower() != "<!doctype html>"))
                {
                    e.ErrMessage = "掌柜--" + this._nickName + "--首页--" + this._shopUrl + "--HTML代码不满足条件";
                    e.ErrPosition = "ShopIndex:InitTaobaoTmallDp()=>if (titleTemp.Contains(淘宝网)";
                    this.ShowErrHandler(lblInfo, e);
                    logger.WriteErrorLog(e.ErrPosition+e.ErrMessage);
                }
                else
                { 
                    ret=InitTaobaoTmallDp(htmlStr);
                }
            }
            else
            {
                e.ErrMessage = "掌柜--" + this._nickName + "--首页--" + this._shopUrl + "--Title不满足条件";
                e.ErrPosition = "ShopIndex:InitDianpuIndex()=>else";
                this.ShowErrHandler(lblInfo, e);
                logger.WriteErrorLog(e.ErrPosition+e.ErrMessage);
            }
            e.ErrPosition="ShopIndex:InitDianpuIndex()";
            e.ErrMessage = "掌柜--" + this._nickName + "--的信息采集成功";
            this.ShowErrHandler(lblInfo, e);
            //e.ErrMessage = "可用代理IP数：" + ipCount + "\r\n" + "IP索引：" + ipIndex + "\r\n" + "本次使用IP：" + currentIP;
            //this.ShowErrHandler(lblIpInfo, e);
            return ret;
        }
        /// <summary>
        /// 初始淘宝旺铺和天猫店
        /// </summary>
        /// <param name="htmlStr"></param>
        private int InitTaobaoTmallDp(string htmlStr)
        {
            ShowErrorLogEventArgs e = new ShowErrorLogEventArgs();
            HtmlAgilityPack.HtmlDocument htmlDoc = GlobalFun.ParaseToHtml(htmlStr);
            try
            {
                string title = htmlDoc.DocumentNode.SelectNodes("//title")[0].InnerText.Trim();
                string script = htmlDoc.DocumentNode.SelectNodes("//script")[0].InnerText;
                _shopTitle = title.Split('-')[1];

                //此处注意子串的长度设置，由于网络传输数据的加密会使其更长。
                this._shopId = script.Substring(script.IndexOf("shopId"), 30).Split(new char[] { ':', ',', '"' })[3];
                this._userId = script.Substring(script.IndexOf("userId"), 30).Split(new char[] { ':', ',', '"' })[3];
                this._nickName = System.Web.HttpUtility.UrlDecode(script.Substring(script.IndexOf("user_nick"), 200).Split(new char[] { ':', ',', '"' })[3]);
                this._sjName = System.Web.HttpUtility.UrlDecode(script.Substring(script.IndexOf("design_nick"), 150).Split(new char[] { ':', ',', '"' })[3]);
                if (_sjName != "")
                {//此处代码要考虑各种版本页面的HTML代码。
                    HtmlAgilityPack.HtmlNode htnSpan = null;
                    if (htmlStr.Contains("id=\"copyright\""))
                    {
                        htnSpan = htmlDoc.DocumentNode.SelectNodes("//div[@id='copyright']")[0];
                        if (htnSpan.InnerText.Contains("店铺设计"))
                        {
                            htnSpan = htmlDoc.DocumentNode.SelectNodes("//div[@id='copyright']/descendant::span/descendant::a")[0];
                        }
                        else
                        {
                            htnSpan = null;
                        }
                    }
                    if (htmlStr.Contains("id=\"wangpu-copyright\""))
                    {
                        htnSpan = htmlDoc.DocumentNode.SelectNodes("//div[@id='wangpu-copyright']/descendant::span/descendant::a")[0];
                    }
                    if (htnSpan != null)
                    {
                        _templateID = htnSpan.Attributes["href"].Value.Split('=')[1];
                    }
                    else
                    {
                        _templateID = "";
                    }
                }
                else
                {
                    _templateID = "";
                }
                if (title.Contains("天猫Tmall.com"))
                {
                    _xyRank = "0";
                    _dpVer = "天猫店铺";
                    _createDate = "";
                }
                if (title.Contains("淘宝网"))
                {
                    //没有等级情况的考虑不够
                    HtmlAgilityPack.HtmlNodeCollection rankNodeCollection = htmlDoc.DocumentNode.SelectNodes("//img[@class='rank']");
                    if (rankNodeCollection == null)
                        _xyRank = "<11";
                    else
                        _xyRank = RankImage(rankNodeCollection[0].Attributes["src"].Value);
                    _dpVer = DianpuVer(htmlStr);
                    _createDate = CreateDianpuDate(htmlDoc);
                }
            }
            catch (Exception ex)
            {
                e.ErrPosition = "ShopIndex:InitTaobaoTmallDp()=>catch";
                e.ErrMessage = "掌柜--" + this._nickName + "--店铺--" + this._shopUrl + "--信息异常--" + ex.Message;
                this.ShowErrHandler(new System.Windows.Forms.Label(), e);
                logger.WriteErrorLog(e.ErrPosition+e.ErrMessage);
                return 0;
            }
            return 1;
        }



        private HtmlAgilityPack.HtmlDocument ParseToHtml(string html)
        {
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.LoadHtml(html);
            return htmlDoc;
        }

        private string CreateDianpuDate(HtmlAgilityPack.HtmlDocument htmlDoc)
        {
            //HtmlAgilityPack.HtmlDocument htmlDoc = ParseToHtml(html);
            string createTime = "";
            //此处如此判断会有问题，有时候可能页面含有这样的串。不科学的方法，分析两者的页面可知，
            //对于老的店铺含有“店铺信息”有这样节结点<div class="shop-details"><h4>店铺信息</h4>
            //新的店铺有<div class="bd-left shop-intro">
            HtmlAgilityPack.HtmlNodeCollection hncOld = htmlDoc.DocumentNode.SelectNodes("//div[@class='shop-details']");
            HtmlAgilityPack.HtmlNodeCollection hncNew = htmlDoc.DocumentNode.SelectNodes("//div[@class='bd-left shop-intro']");

            if (hncOld != null)
            {
                createTime = htmlDoc.DocumentNode.SelectNodes("//li[@class='setuptime']")[0].ChildNodes[1].InnerText;
            }
            if (hncNew != null)
            {
                createTime = htmlDoc.DocumentNode.SelectNodes("//div[@class='bd-left shop-intro']")[0].SelectNodes("//span[@class='text']")[3].InnerText;
                string[] time = createTime.Split('年', '月', '日');
                createTime = time[0] + "-" + time[1] + "-" + time[2];
            }
            return createTime;
        }

        /// <summary>
        /// 根据传的img src=""图片属性得到信用等级图片，本地存储，加快网络速度。
        /// 如 http://pics.taobaocdn.com/newrank/s_blue_5.gif
        ///    http://pics.taobaocdn.com/newrank/s_red_4.gif
        ///    http://pics.taobaocdn.com/newrank/s_crown_1.gif
        /// </summary>
        /// <param name="rankURL"></param>
        /// <returns></returns>
        public string RankImage(string rankURL)
        {
            string levelImg = rankURL.Split('/')[4];
            return levelImg;
        }

        /// <summary>
        /// 根据页面信息得到相应的版本  
        /// </summary>
        /// <param name="ver">传入的HTML信息</param>
        /// <returns>2012新旺铺专业版   2012新旺铺基础版  天猫店铺  旺铺扶植版  旺铺标准版  旺铺拓展版  旺铺旗舰版</returns>
        public string DianpuVer(string html)
        {
            string retVer = "";
            if (html.Contains("http://img04.taobaocdn.com/tps/i4/T1prA2XhlhXXcgU5U6-113-21.png"))
                retVer = "2012新旺铺基础版";
            else if (html.Contains("http://img01.taobaocdn.com/tps/i1/T1lKXaXp4hXXcgU5U6-113-21.png"))
                retVer = "2012新旺铺专业版";
            else if (html.Contains("标准版"))
                retVer = "旺铺标准版";
            else if (html.Contains("扶植版"))
                retVer = "旺铺扶植版";
            else if (html.Contains("拓展版"))
                retVer = "旺铺拓展版";
            else if (html.Contains("旗舰版"))
                retVer = "旺铺旗舰版";
            else
                retVer = "天猫店铺";
            return retVer;
        }
    }
}